package model;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import view.ClientGameBoard;
import view.FileMenu;
import controller.KeyboardListener;

@SuppressWarnings("serial")
public class GameClient extends JFrame
{

	private Socket socket;

	private static final int PORTNUM = 10055;
	private static final String ADDRESS = "localhost";

	private PrintWriter outputToServer;
	private BufferedReader inputFromServer;

	private boolean isConnected = false;
	private boolean gameStarted = false;

	private ClientGameBoard cgb = new ClientGameBoard(this);

	private ClientPlayer cP;

	private FileMenu filemenu = new FileMenu(this);

	private int start = 0;

	public ClientPlayer getCP()
	{
		return cP;
	}

	public void setCP(int xCoord, int yCoord)
	{
		cP = new ClientPlayer(true, xCoord, yCoord);
	}

	public static void main(String args[])
	{
		new GameClient();
	}

	/*
	 * Sending numbers to the server
	 * 
	 * +-------------+------------------------------------------------+ | NUMBER
	 * SENT | WHAT IT MEANS |
	 * +-------------+------------------------------------------------+ | 1, 2,
	 * 3, 4 | Top Left, Top Right, Bottom Left, Bottom Right | | 5 | Create a
	 * game | | 6 | Queue for a game |
	 * +-------------+------------------------------------------------+
	 */

	public GameClient()
	{
		setLayout(new BorderLayout());
		setJMenuBar(filemenu);

		add(cgb, BorderLayout.CENTER);
		addKeyListener(new KeyboardListener(this));

		setSize(800, 820);
		setTitle("********** Monster Munchies **********");
		setResizable(false);
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		setVisible(true);
		setLocationRelativeTo(null);

		/*
		 * JOptionPane.showMessageDialog(getContentPane(),
		 * "1. Connect to the Game Server from the Menu\n" +
		 * "2. Select Create game to start playing!"
		 * ,"Welcome to Monster Munchies!",JOptionPane.INFORMATION_MESSAGE);
		 */

		this.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				promptClose();
			}
		});
	}

	@SuppressWarnings("unused")
	public void actionPerformed(ActionEvent e)
	{
		String actionCommand = e.getActionCommand();
	}

	public void promptClose()
	{
		int response = JOptionPane.showConfirmDialog(null,
				"Do you want to exit?", "Exit Program??",
				JOptionPane.YES_NO_OPTION);
		if (response == JOptionPane.YES_OPTION)
		{
			System.exit(0);
		}
	}

	public PrintWriter getOutputToServer()
	{
		return outputToServer;
	}

	public void setOutputToServer(PrintWriter outputToServer)
	{
		this.outputToServer = outputToServer;
	}

	public BufferedReader getInputFromServer()
	{
		return inputFromServer;
	}

	public void setInputFromServer(BufferedReader inputFromServer)
	{
		this.inputFromServer = inputFromServer;
	}

	public int getPortNum()
	{
		return PORTNUM;
	}

	public String getAddress()
	{
		return ADDRESS;
	}

	public boolean isStarted()
	{
		return gameStarted;
	}

	public boolean checkConnected()
	{
		return isConnected;
	}

	public void setConnected()
	{
		isConnected = true;
	}

	public Socket getSocket()
	{
		return socket;
	}

	public int getStart()
	{
		return start;
	}

	public void setStart(int start)
	{
		this.start = start;
	}

	public ClientGameBoard getCGB()
	{
		return cgb;
	}

	public synchronized void createSocket()
	{
		try
		{
			this.socket = new Socket(ADDRESS, PORTNUM);
		}
		catch (ConnectException ex)
		{
			// Connect Exception will happen here
			// System.out.println("Connection refused, please check your local network settings");
			JOptionPane.showMessageDialog(getContentPane(),
					"Failed to connect to server.\nPlease "
							+ "check your local network settings",
					"Connection Error", JOptionPane.ERROR_MESSAGE);
		}
		catch (IOException e)
		{
			System.out.println("IO exception occured. Please review");
		}
		catch (Exception e)
		{
			System.out.println("Normal exception occured. Please review");
		}
	}

	@SuppressWarnings("unused")
	public void chooseSide()
	{
		boolean sideChosen = false;
		try
		{
			int sent = 0;
			do
			{
				/*
				 * A dialog box will appear with 4 options to choose from. Each
				 * will correspond to the side where the user will start from
				 */
				System.out.println("CHOOSING SIDE");
				Object[] possibilities = { "1", "2", "3", "4" };
				Object[] options = { "OK", "CANCEL" };
				String s = (String) JOptionPane
						.showInputDialog(
								this,
								"1 = Top Left, 2 = Top Right\n3 = Bottom Left, 4 = Bottom Right",
								"Pick a Side", JOptionPane.PLAIN_MESSAGE, null,
								possibilities, "Top Left");

				// Send chosen side to the server (Change Strings to Integers)
				int sentNumber = Integer.parseInt(s);

				getOutputToServer().write(sentNumber);
				getOutputToServer().flush();

				// Get input from the Server side, reads the int that is
				// returned
				int choose = getInputFromServer().read();

				// 0 from the server means OK, your spot is reserved
				// if (inInt == 0){
				if (choose == 1)
				{
					JOptionPane
							.showMessageDialog(
									getContentPane(),
									"Your side has been selected!\nPlease wait for other players",
									"Side Selected",
									JOptionPane.INFORMATION_MESSAGE);
					sideChosen = true;
					sent = sentNumber;
				}
				else
				{
					JOptionPane.showMessageDialog(getContentPane(),
							"This side has been taken\nPlease "
									+ "pick another side",
							"Side has been taken", JOptionPane.ERROR_MESSAGE);
				}
			}
			while (sideChosen == false);
			System.out.println("A side has been chosen, " + sent);
			gameStarted = true;
			setStart(sent);
			updateBoard();
		}
		catch (Exception ex)
		{
			System.out
					.println("Exception while choosing side occured. Please review");
		}
	}

	public void updateBoard()
	{

		try
		{
			this.getCGB().removeAll();
			this.getCGB().setStage();
			this.getCGB().validate();
			this.getCGB().repaint();

			System.out.println("The Board has been updated");
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}

	}

	public void startGame()
	{
		// Refresh game board, with all players and server generates a monster
		// in the middle
		// Makes sure that the server creates a monster

		try
		{
			// do{
			// client constantly updates the board with updateBoard()
			// }while (server is running);

			// while (true){
			// do all the concurrency stuff, includes board updating
			// }

		}
		catch (Exception ex)
		{
			// TODO Auto-generated catch block
			System.out
					.println("Exception in Start Game method occured. Please review");
		}
	}

	public boolean move(int movement)
	{
		try
		{
			// Send tile to move to, to the server
			int moveInteger[] = { 7, 8, 9, 10 };

			// Server interprets 7 as Up, 8 as Down, 9 as Left, 10 as Right
			getOutputToServer().write(moveInteger[movement]);
			getOutputToServer().flush();

			// Get input from the Server side, reads the int that is returned
			// int inInt = getInputFromServer().readInt();
			int move = getInputFromServer().read();

			// 0 from the server means OK, your spot is reserved
			// if (inInt == 0){
			if (move == 1)
			{

				int moveUp = 0;
				int moveLeft = 0;

				if (moveInteger[movement] == 7)
				{
					moveUp = -1;
				}
				else if (moveInteger[movement] == 8)
				{
					moveUp = 1;
				}
				else if (moveInteger[movement] == 9)
				{
					moveLeft = -1;
				}
				else
				{
					moveLeft = 1;
				}

				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX() + moveUp,
						cP.getPosY() + moveLeft);
				this.getCGB().validate();
				this.getCGB().repaint();
			}
			else
			{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(), cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();

			}
			System.out.println("The Board has been updated with movement");
			return true;
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			System.out.println("Error with moving");
		}
		return false;
	}

	public boolean teleport()
	{
		try
		{
			// Tells server I want to teleport to [4,4]
			getOutputToServer().write(11);
			getOutputToServer().flush();

			int allowTeleport = getInputFromServer().read();

			if (allowTeleport == 1)
			{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(4, 4);
				this.getCGB().validate();
				this.getCGB().repaint();

				System.out.println("Your Teleport has been granted");
			}
			else if (allowTeleport == 2)
			{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(), cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();
				System.out
						.println("Teleport Refused: Another player is at 4:4");
			}
			else
			{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(), cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();
				System.out
						.println("Teleport Refused: You have ran out of teleports");
			}

			return true;
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			System.out.println("Error with teleporting");
		}
		return false;
	}
}
